#!/bin/bash
#
# passgen - create strong passwords from easy-to-remember strings
#
# This is a fork of the Password generator from the one in JXSelf's post:
#
#     https://jxself.org/password-generator.shtml
#
# In his original proposal, Jonathan suggests taking a hash of a relatively
# weak password composed of a password seed (called there a "salt") combined
# with a service-specific identifier (called a "string") and encoding it with
# base64 to produce a 32 character strong-looking password.
#
# However, it ocurred to me that perhaps these passwords may be easy to reverse
# in case it becomes known that you indeed generate your passwords using this 
# method. All the attacker has to do is realize that the password looks like a
# base64-encoded string (easy to infer from the pattern of the string).
#
# For example, suppose you use the salt "banana" and the string "example.com"
# to get the password YmFmNzc1MjQ1MWJlMWI2Y2IyNGQyNjJk. Decoding that, we get:
# baf7752451be1b6cb24d262d, a slice of the original hash. That information 
# could be used to figure out parts of the hashed string, most importantly the
# common salt used accross all passwords...
# 
# My modifications include the insertion of additional methods for making the
# reversibility harder, and the usage of more non-alphanumeric characters 
# through the usage of tr.
#
# --------
# Short history:
# 0.1-ALPHA - first usable release
# --------
#
#    Copyright (C) 2016 - kzimmermann <https://quitter.se/kzimmermann>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

while [ true ];
do
    printf "Enter your salt: "
    read -s SALT
    printf "\n"
    printf "Confirm: "
    read -s SALT_CONFIRM
    echo -en "\n"
    if [ "$SALT" == "$SALT_CONFIRM" ]; then
        break
    fi
    echo "Salts don't match. Please try again."
done
if [[ -z "$1" ]]
then
    printf "Enter your string: "
    read STRING
else
    STRING="$1"
fi

HASH=$(printf "$SALT$STRING" | sha512sum | cut -d " " -f 1)
HASH2=$(printf "$STRING$SALT" | sha512sum | cut -d " " -f 1)
REV=$(printf $HASH | rev)

# Yes, enough readable characters come out of this mess.
PASSWORD=$(
    printf "$REV$HASH$HASH2" | 
        base64 -d 2> /dev/null |
        tr -dc [:graph:]
)

echo ${PASSWORD:0:32}
echo "Copy and press enter to finish"
read 

# clear screen safely so to make difficult scrolling back to read it.
for ((i=0; i < 500; i++))
do
    printf "\n\n\n"
done
clear

